//@author A0086393U
package rightnow.ui;

import java.io.IOException;
import java.net.URL;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.text.Font;
import javafx.stage.Stage;

import org.jnativehook.NativeHookException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Entry point of the program. Loads the resources required to start the
 * application and initializes the relevant windows to display.
 */
public class MainApp extends Application {
	private static final Logger LOG = LoggerFactory.getLogger(MainApp.class);

	private static final String MAIN_SCENE_CSS = "/styles/main-scene.css";
	private static final String MAIN_VIEW_FXML = "/fxml/MainView.fxml";
	private static final String MAIN_VIEW_TITLE = "rightNOW";
	
	private static final String ROBOTO_LOCATION = "/fonts/Roboto-Regular.ttf";
	private static final String ROBOTOSLAB_LOCATION = "/fonts/RobotoSlab-Regular.ttf";
	private final URL robotoUrl = getClass().getResource(ROBOTO_LOCATION);
	private final URL robotoSlabUrl = getClass().getResource(ROBOTOSLAB_LOCATION);
	
	private static GlobalHotKeys hotkey;
	private static Parent rootNode;
	private static Scene mainScene;
	
	public static void main(String[] args) {
		launch(args);
	}

	// Called automatically by JavaFX
	public void start(Stage stage) throws IOException, NativeHookException {
		LOG.info("Starting rightNOW");
		LOG.debug("Initializing JFX scene");
		
		loadFonts();
		initializeSceneAndPresenter(stage);
		initializeGlobalHotkeys(this, stage);
		initializeAndShowMainStage(stage, mainScene);
		
		LOG.debug("Stage successfully shown");
	}

	// Override Application.stop() to release global hotkeys
	@Override
	public void stop() {
		if (hotkey != null) {
			hotkey.release();
			LOG.debug("Hotkeys released");
		}
		LOG.info("Application successfully terminated");
		Platform.exit();
		System.exit(0);
	}
	
	// Loads the FXML of the main scene and its controller and sets them up.
	private void initializeSceneAndPresenter(Stage stage) throws IOException {
		LOG.debug("Loading FXML for main view from: {}", MAIN_VIEW_FXML);

		URL mainViewFxmlUrl = getClass().getResource(MAIN_VIEW_FXML);
		FXMLLoader loader = new FXMLLoader();
		loader.setLocation(mainViewFxmlUrl);

		rootNode = (Parent) loader.load(mainViewFxmlUrl.openStream());
		
		// Setup stage
		mainScene = new Scene(rootNode);
		mainScene.getStylesheets().add(MAIN_SCENE_CSS);
	}
	
	private void initializeGlobalHotkeys(MainApp mainApp, Stage stage) throws NativeHookException {
		hotkey = new GlobalHotKeys();
		hotkey.setStageToMaxiMin(stage);
		
		// Add shutdown hook to release global hotkeys on forced termination
		Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
			@Override
			public void run() {
				hotkey.release();
			}
		}));
	}
	
	private void initializeAndShowMainStage(Stage stage, Scene mainScene) {
		stage.setTitle(MAIN_VIEW_TITLE);
		stage.setResizable(false);
		stage.setScene(mainScene);
		// stage.getIcons().add(new Image("file path"));
		stage.show();
	}
	
	private void loadFonts() {
		if (Font.loadFont(robotoUrl.toExternalForm(), 12) == null) {
			LOG.debug("Failed to load font: " + robotoUrl.toExternalForm());
		} else {
			LOG.debug(robotoUrl.toExternalForm() + " successfully loaded.");
		}
		if (Font.loadFont(robotoSlabUrl.toExternalForm(), 12) == null) {
			LOG.debug("Failed to load font: " + robotoSlabUrl.toExternalForm());
		} else {
			LOG.debug(robotoSlabUrl.toExternalForm() + " successfully loaded.");
		}
	}
}
